package cn.edu.nju.ws.sview.reasoning.test;

import java.sql.SQLException;
import java.util.ArrayList;
import java.util.HashSet;

import cn.edu.nju.ws.sview.rdf.RDFFactory;
import cn.edu.nju.ws.sview.rdf.ResourceFactory;
import cn.edu.nju.ws.sview.rdf.URIResource;
import cn.edu.nju.ws.sview.reasoning.Atom;
import cn.edu.nju.ws.sview.reasoning.Constant;
import cn.edu.nju.ws.sview.reasoning.GroundAtom;
import cn.edu.nju.ws.sview.reasoning.KnowledgeBase;
import cn.edu.nju.ws.sview.reasoning.Predicate;
import cn.edu.nju.ws.sview.reasoning.ProductionMemory;
import cn.edu.nju.ws.sview.reasoning.Repository;
import cn.edu.nju.ws.sview.reasoning.Rule;
import cn.edu.nju.ws.sview.reasoning.Term;
import cn.edu.nju.ws.sview.reasoning.Variable;
import cn.edu.nju.ws.sview.reasoning.WorkingMemory;
import cn.edu.nju.ws.sview.reasoning.provenance.FromSchemaReasoning;
import cn.edu.nju.ws.sview.reasoning.provenance.ProvenanceFactory;

import com.hp.hpl.jena.ontology.OntModel;
import com.hp.hpl.jena.rdf.model.ModelFactory;
import com.hp.hpl.jena.rdf.model.Property;
import com.hp.hpl.jena.rdf.model.Resource;
import com.hp.hpl.jena.vocabulary.RDF;

public class test3 {
	//type = 0 constant, type = 1 variable
	public static Atom<Term> createAtom(int arity,String predSymbol,int[] types,String[] values) throws SQLException{
		Predicate predicate = new Predicate(ResourceFactory.getInstance().createURIResource("test3/"+predSymbol),arity);
		ArrayList<Term> list = new ArrayList<Term>();
		for(int i=0;i<arity;i++){
			String value = values[i];
			Term term;
			if(types[i]==0){
				 term = new Constant(ResourceFactory.getInstance().createURIResource("test3/"+value));
			}else{
				term = new Variable(value) ;
			}
			list.add(term) ;
		}
		Atom<Term> atom = new Atom<Term>(predicate,list);
		return atom;
	}
	public static void main(String[] args) throws SQLException{
		Repository.getInstance();
		OntModel model = ModelFactory.createOntologyModel();	
    	WorkingMemory wm =new WorkingMemory();
    	ProductionMemory pm = new ProductionMemory();
    	//class Facts   course("COURSE01"). university("NJU"). university("SEU"). phdTutor("Gu").phdStudent("Zhang"). phdStudent("Li")
    	String[] fcPredSymbol = {"course","university","university","phdTutor","phdStudent","phdStudent"};
    	String[] fcFirst ={"COURSE01","NJU","SEU","Gu","Zhang","Li"};
    	 HashSet<GroundAtom> facts = new HashSet<GroundAtom>();
    	for(int i = 0;i<6;i++){
    	    URIResource pred = ResourceFactory.getInstance().createURIResource("test3/"+fcPredSymbol[i]);
    	    URIResource arg =  ResourceFactory.getInstance().createURIResource("test3/"+fcFirst[i]);
    	    Constant s = new Constant(arg);
    	    ArrayList<Constant> list = new ArrayList<Constant>();
    	    list.add(s) ;
    	    Predicate predicate = new Predicate(pred,1);
    	    GroundAtom fact = new GroundAtom(predicate,list,ProvenanceFactory.getInstance().createProvFromDataMembers());
    	    facts.add(fact);
    	}
    	
    	    	//property Facts  hasPreCourse("COURSE01","COURSE02").hasPreCourse("COURSE01","COURSE03").hasPreCourse("COURSE02","COURSE04").
    	    	//teach("Ni","COURSE01").teach("Wu","COURSE03").teach("Zhang","COURSE04").teach("Feng","COURSE02").
    	    	//workAt("Ni","SEU").workAt("Wu","SEU").
    	    	//hasFounder("Zhou","Ni").hasFounder("Tang","Ni").
    	    	//hasStudent("Gu","Ni").hasStudent("Wu","Chen").hasStudent("Zhou","Feng").
    	    	//hasAdvisor("Zhang","Ni").hasAdvisor("Gu","Wang").hasAdvisor("Wu","Gu").hasAdvisor("Li","Wu").hasAdvisor("Gang","Ni").hasAdvisor("Zhou","Tang").
    	String[] fPredSymbol = {"hasPreCourse","hasPreCourse","hasPreCourse","teach","teach","teach","teach","workAt","workAt","hasFounder","hasFounder","hasStudent","hasStudent","hasStudent","hasAdvisor","hasAdvisor","hasAdvisor","hasAdvisor","hasAdvisor","hasAdvisor"};
    	String[] fFirst = {"COURSE01","COURSE01","COURSE02","Ni","Wu","Zhang","Feng","Ni","Wu","Zhou","Tang","Gu","Wu","Zhou","Zhang","Gu","Wu","Li","Gang","Zhou"};
    	 String[] fSecond ={"COURSE02","COURSE03","COURSE04","COURSE01","COURSE03","COURSE04","COURSE02","SEU","SEU","Ni","Ni","Ni","Chen","Feng","Ni","Wang","Gu","Wu","Ni","Tang"};

    	
    	 for(int i = 0;i<20;i++){
    	    URIResource pred = ResourceFactory.getInstance().createURIResource("test3/"+fPredSymbol[i]);
    	    URIResource arg1 =  ResourceFactory.getInstance().createURIResource("test3/"+fFirst[i]);
    	    URIResource arg2 =  ResourceFactory.getInstance().createURIResource("test3/"+fSecond[i]);
    	    Constant s1 = new Constant(arg1);
    	    Constant s2 = new Constant(arg2);
    	    ArrayList<Constant> list = new ArrayList<Constant>();
    	    list.add(s1) ;
    	    list.add(s2) ;
    	    Predicate predicate = new Predicate(pred,2);
    	    GroundAtom fact = new GroundAtom(predicate,list,ProvenanceFactory.getInstance().createProvFromDataMembers());
    	    facts.add(fact);
    	}

    	//rules  hasFounder(?x,?y):-hasAdvisor(?x,?y). hasFounder(?x,?y):-hasAdvisor(?x,?z),hasFounder(?z,?y).
    	// hasAdvisor(?x,?y):-hasStudent(?y,?x). hasStudent(?x,?y):-hasAdvisor(?y,?x). hasStudent(?x,?y):-hasFounder(?z,?x),hasStudent(?z,?y).
    	//phdStudent(?x):-hasAdvisor(?x,?y),phdTutor(?y). phdTutor(?y):-phdStudent(?x),hasAdvisor(?x,?y).
    	//hasFaculty(?y,?x):-workAt(?x,?y),university(?y).
    	//lecturer(?x):-teach(?x,?y),course(?y).
    	//assistant(?x):-phdStudent(?x),lecturer(?x).
    	//course(?y):-course(?x),hasPreCourse(?x,?y).
		for(int kk=0;kk<1;kk++){
			long start = System.currentTimeMillis();
    	      int[] types = {1,1};
    	      String[] valuesxy = {"x","y"};
    	       String[] valuesyx = {"y","x"};
    	      int[] typesX = {1};
    	      String[] valuesX = {"x"};
    	      String[] valuesY = {"y"};
    	      ArrayList<Atom<Term>> bodyList1 = new ArrayList<Atom<Term>>();
    	     Atom<Term> head_hasFounder = createAtom(2,"hasFounder",types,valuesxy);    
    	     String[][] bvalues1 = {{"x","y"}};
    	     String[] preds1 = {"hasAdvisor"};
    	     for(int i=0;i<1;i++){
    	     		Atom<Term> atom= createAtom(2,preds1[i],types,bvalues1[i]);
    	     		bodyList1.add(atom);
    	     }
    	     Rule rule1 = new  Rule(head_hasFounder,bodyList1,new FromSchemaReasoning());
    	     pm.addRule(rule1) ;
    	     
    	     ArrayList<Atom<Term>> bodyList2 = new ArrayList<Atom<Term>>(); 
    	     String[][] bvalues2 = {{"x","z"},{"z","y"}};
    	     String[] preds2 = {"hasAdvisor","hasFounder"};
    	     for(int i=0;i<2;i++){
    	     		Atom<Term> atom = createAtom(2,preds2[i],types,bvalues2[i]);
    	     		bodyList2.add(atom);
    	     }
    	     Rule rule2= new  Rule(head_hasFounder,bodyList2,new FromSchemaReasoning());
    	     pm.addRule(rule2) ;
    	     
    	     ArrayList<Atom<Term>> bodyList3 = new ArrayList<Atom<Term>>();
    	     Atom<Term> head_hasStudent = createAtom(2,"hasStudent",types,valuesxy);    
    	     String[][] bvalues3= {{"y","x"}};
    	     for(int i=0;i<1;i++){
    	     		Atom<Term> atom = createAtom(2,preds1[i],types,bvalues3[i]);
    	     		bodyList3.add(atom);
    	     }
    	     Rule rule3 = new  Rule(head_hasStudent,bodyList3,new FromSchemaReasoning());
    	     pm.addRule(rule3) ;
    	     
    	     ArrayList<Atom<Term>> bodyList4 = new ArrayList<Atom<Term>>(); 
    	     String[][] bvalues4 = {{"z","x"},{"z","y"}};
    	     String[] preds4 = {"hasFounder","hasStudent"};
    	     for(int i=0;i<2;i++){
    	     		Atom<Term> atom= createAtom(2,preds4[i],types,bvalues4[i]);
    	     		bodyList4.add(atom);
    	     }
    	     Rule rule4= new  Rule(head_hasStudent,bodyList4,new FromSchemaReasoning());
    	     pm.addRule(rule4) ;
    	     
    	     ArrayList<Atom<Term>> bodyList5 = new ArrayList<Atom<Term>>();
    	     Atom<Term> head_hasAdvisor = createAtom(2,"hasAdvisor",types,valuesxy);    
    	     String[] pred5 = {"hasStudent"};
    	     String[][] bvalues5= {{"y","x"}};
    	     for(int i=0;i<1;i++){
    	     		Atom<Term> atom = createAtom(2,pred5[i],types,bvalues5[i]);
    	     		bodyList5.add(atom);
    	     }
    	     Rule rule5 = new  Rule(head_hasAdvisor,bodyList5,new FromSchemaReasoning());
    	     pm.addRule(rule5) ;
    	     
    	     Atom<Term> phdStudentX = createAtom(1,"phdStudent",typesX,valuesX);
    	     Atom<Term> phdTutorY= createAtom(1,"phdTutor",typesX,valuesY);
    	     ArrayList<Atom<Term>> bodyList6 = new ArrayList<Atom<Term>>();
    	      bodyList6.add(head_hasAdvisor);bodyList6.add(phdTutorY);
    	     Rule rule6 = new  Rule(phdStudentX,bodyList6,new FromSchemaReasoning());
    	     pm.addRule(rule6) ;  
    	     ArrayList<Atom<Term>> bodyList7 = new ArrayList<Atom<Term>>();
    	      bodyList7.add(phdStudentX);bodyList7.add(head_hasAdvisor);
    	     Rule rule7 = new  Rule(phdTutorY,bodyList7,new FromSchemaReasoning());
    	     pm.addRule(rule7) ;  
    	     
    	     Atom<Term> HasFaculty = createAtom(2,"hasFaculty",types,valuesyx);
    	     ArrayList<Atom<Term>> bodyList8 = new ArrayList<Atom<Term>>();
    	      Atom<Term> workAt = createAtom(2,"workAt",types,valuesxy);    
    	      Atom<Term> university= createAtom(1,"university",typesX,valuesY);
    	      bodyList8.add(workAt);
    	      bodyList8.add(university);
    	        Rule rule8 = new  Rule(HasFaculty,bodyList8,new FromSchemaReasoning());
    	     pm.addRule(rule8) ;  
    	     
    	     Atom<Term> lecturer = createAtom(1,"lecturer",typesX,valuesX);
    	     ArrayList<Atom<Term>> bodyList9 = new ArrayList<Atom<Term>>();
    	      Atom<Term> teach = createAtom(2,"teach",types,valuesxy);    
    	      Atom<Term> course= createAtom(1,"course",typesX,valuesY);
    	      bodyList9.add(teach);
    	      bodyList9.add(course);
    	        Rule rule9 = new  Rule(lecturer,bodyList9,new FromSchemaReasoning());
    	     pm.addRule(rule9) ;  
    	     
    	     Atom<Term> assistant = createAtom(1,"assistant",typesX,valuesX);
    	     ArrayList<Atom<Term>> bodyList10 = new ArrayList<Atom<Term>>();
    	      bodyList10.add(phdStudentX);
    	      bodyList10.add(lecturer);
    	        Rule rule10 = new  Rule(assistant,bodyList10,new FromSchemaReasoning());
    	     pm.addRule(rule10) ;  
    	     
    	     ArrayList<Atom<Term>> bodyList11 = new ArrayList<Atom<Term>>();  
    	      Atom<Term> courseX= createAtom(1,"course",typesX,valuesX);
    	     Atom<Term> hasPreCourse = createAtom(2,"hasPreCourse",types,valuesxy);    
    	      bodyList11.add(courseX);
    	      bodyList11.add(hasPreCourse);
    	        Rule rule11 = new  Rule(course,bodyList11,new FromSchemaReasoning());
    	     pm.addRule(rule11) ;  
    	  //    System.out.println("[INFO]loading rules completes");
     /**new a knowledge base**/
       KnowledgeBase kb = new KnowledgeBase(wm,pm);
       for(GroundAtom atom:facts){
    	   kb.addFact(atom) ;
       }
/*Add a query */
       int[] x ={1};
       String[] y = {"x"};
    	Atom<Term> q = createAtom(1,"assistant",x,y);
	   HashSet<GroundAtom> ans = kb.Evaluate(q,true) ;
		long time = System.currentTimeMillis()-start;
		System.out.println("Time: "+time);
	   System.out.println(kb.toString());
 	   System.out.println("Query "+q.toString()+"\n");
	   System.out.println("Answer:\n ");
	   for(GroundAtom fact:ans){
		   System.out.println(fact);
	   }
	}   
	}


}
